package edu.cs.usask.ca.silver.businesslogic.commands.generic;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.UUID;

import edu.cs.usask.ca.silver.api.businesslogic.UserI;
import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.businesslogic.ids.GroupID;
import edu.cs.usask.ca.silver.businesslogic.ids.UserID;
import edu.cs.usask.ca.silver.businesslogic.util.SilverAutoManagedObjectFactory;
import edu.cs.usask.ca.silver.businesslogic.util.SilverBLTransactionManager;
import edu.cs.usask.ca.silver.definitions.Exposure;

/**
 * This class is an implementation of the user interface.
 * 
 * @author Yudi Xue
 */
public class User implements UserI {

	private static final SilverAutoManagedObjectFactory userFactory = new SilverAutoManagedObjectFactory(
			"edu.cs.usask.ca.silver.businesslogic.commands.generic.User");

	public static SilverAutoManagedObjectFactory getObjectPoolFactory() {
		return userFactory;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#createUser(java.lang.String
	 * , java.lang.String, java.lang.String, java.lang.String)
	 */
	public UserID createUser(String uFirstName, String uLastName,
			String uEmail, String uPasswd, StorageI storage) throws Exception {

		UserID result;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();

			UUID uIdUUID = storage.addUser(uFirstName,
					uLastName, uEmail, uPasswd);
			UUID gIdUUID = storage.addGroup(
					Exposure.PRIVATE.name(), uIdUUID, Exposure.PRIVATE.name(),
					"private group for" + uFirstName);

			storage.setUserPrivateGroupId(uIdUUID, gIdUUID);
			storage.addUserToGroup(uIdUUID, gIdUUID);
			result = new UserID(uIdUUID);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getBasicInfo(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID)
	 */
	public String[] getBasicInfo(UserID userID, StorageI storage) throws Exception {
		return storage.getUserBasicInfoIntoStringArray(
				userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.UserI#getAllUserIds()
	 */
	public UserID[] getAllUserIds(StorageI storage) throws Exception {
		ArrayList<UUID> result;
		result = storage.getAllUserIDs();
		UserID[] ids = new UserID[result.size()];
		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			ids[i++] = new UserID(e.next());
		}

		return ids;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getFirstName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID)
	 */
	public String getFirstName(UserID userID, StorageI storage) throws Exception {
		return storage.getUserFirstName(userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getLastName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID)
	 */
	public String getLastName(UserID userID, StorageI storage) throws Exception {
		String result;
		result = storage
				.getUserLastName(userID.getUUIdVal());
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getEmail(edu.cs.usask.
	 * ca.silver.businesslogic.ids.UserID)
	 */
	public String getEmail(UserID userID, StorageI storage) throws Exception {
		return storage.getUserEmail(userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getPrivateGroupID(edu.
	 * cs.usask.ca.silver.businesslogic.ids.UserID)
	 */
	public GroupID getPrivateGroupID(UserID userID, StorageI storage) throws Exception {
		return new GroupID(storage.getUserPrivateGroupId(
				userID.getUUIdVal()));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.UserI#
	 * getUserIDFromEmailAndPassCombination(java.lang.String, java.lang.String)
	 */
	public UserID getUserIDFromEmailAndPassCombination(String uEmail,
			String uPasswd, StorageI storage) throws Exception {
		return new UserID(storage
				.getUserIdentityBasedOnEmailAndPassword(uEmail, uPasswd));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#verifyPassWord(edu.cs.
	 * usask.ca.silver.businesslogic.ids.UserID, java.lang.String)
	 */
	public boolean verifyPassWord(String uEmail, String uPass, StorageI storage) throws Exception {
		return storage.verifyUserPassword(uEmail, uPass);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getRegistrationDate(edu
	 * .cs.usask.ca.silver.businesslogic.ids.UserID)
	 */
	public Date getRegistrationDate(UserID userID, StorageI storage) throws Exception {
		return storage.getUserRegistrationDate(
				userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getUserRegistrationTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.UserID)
	 */
	public Date getUserRegistrationTime(UserID userID, StorageI storage) throws Exception {
		return storage.getUserRegistrationTime(
				userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#getParticipatedGroupIds
	 * (edu.cs.usask.ca.silver.businesslogic.ids.UserID)
	 */
	public GroupID[] getParticipatedGroupIds(UserID userID, StorageI storage) throws Exception {
		ArrayList<UUID> result;

		result = storage.getUserParticipatedGroupIds(
				userID.getUUIdVal());
		GroupID[] ids = new GroupID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			ids[i++] = new GroupID(e.next());
		}
		return ids;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#setFirstName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID, java.lang.String)
	 */
	public boolean setFirstName(UserID userID, String updatedFirstName, StorageI storage)
			throws Exception {
		return storage.setUserFirstName(userID.getUUIdVal(),
				updatedFirstName);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#setLastName(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID, java.lang.String)
	 */
	public boolean setLastName(UserID userID, String updatedLastName, StorageI storage)
			throws Exception {
		return storage.setUserLastName(userID.getUUIdVal(),
				updatedLastName);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#setEmail(edu.cs.usask.
	 * ca.silver.businesslogic.ids.UserID, java.lang.String)
	 */
	public boolean setEmail(UserID userID, String updatedEmail, StorageI storage)
			throws Exception {
		return storage.setUserEmail(userID.getUUIdVal(),
				updatedEmail);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#setPasswd(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID, java.lang.String)
	 */
	public boolean setPasswd(UserID userID, String updatedPasswd, StorageI storage)
			throws Exception {
		return storage.setUserPasswd(userID.getUUIdVal(),
				updatedPasswd);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.UserI#deleteUser(edu.cs.usask
	 * .ca.silver.businesslogic.ids.UserID)
	 */
	public boolean deleteUser(UserID userID, StorageI storage) throws Exception {
		return storage.deleteUser(userID.getUUIdVal());
	}

}
